﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Arcadium.Graphics;
using Arcadium.Audio;

namespace Arcadium.GameEntities.Characters
{
    /// <summary>
    /// Extends the Character to be processed with its own updating, although, 
    /// no input is gathered, just the possibilities with gravity and collision.
    /// </summary>
    abstract class UpdatableCharacter : Character
    {
        #region Field

        protected Vector2 velocity;

        private bool onGround;
        private TimeSpan? jumpTime;
        private TimeSpan maxJumpTime = TimeSpan.FromSeconds(.15f);

        #endregion

        #region Properties

        public bool GravitationEnabled
        {
            get;
            set;
        }
        public float? Gravity
        {
            get;
            set;
        }
        public static float StandardGravity
        {
            get { return .09f; }
        }

        public bool IsJumping
        {
            get { return jumpTime.HasValue; }
        }

        public float Speed
        {
            get;
            set;
        }
        public bool OnGround
        {
            get { return onGround; }
        }

        #endregion

        #region Initialization
        
        /// <summary>
        /// Constructs a new Character.
        /// </summary>
        public UpdatableCharacter(World world)
            : base(world)
        {
            this.GravitationEnabled = true;
            this.Speed = .8f;
        }

        #endregion

        #region Update

        /// <summary>
        /// Implements standard behaviour for all characters, affected by gravity and obays collision.
        /// Also, dies 
        /// </summary>
        /// <param name="gameTime"></param>
        /// <returns></returns>
        public override bool Update(GameTime gameTime)
        {
            // Gravity
            if (GravitationEnabled)
            {
                this.velocity.Y +=
                    (Gravity.HasValue ? Gravity.Value : StandardGravity);
                onGround = false;
            }

            if (IsJumping)
                BuildUpJump(gameTime.ElapsedGameTime);

            Vector2 pos = Position;
            World.Map.CheckCollision(gameTime, ref pos, ref velocity, ref onGround, Origin);
            Position = pos;

            if (velocity.X != 0)
                this.Direction = (int)(velocity.X / Math.Abs(velocity.X));


            // Collision check for enemies.
            //if (checkEnemyCollision)
            //{
            //    foreach (Character enemy in World.Enemies)
            //    {
            //        if (enemy == this)
            //            continue;
            //        if (GetBoundingRectangle().Intersects(enemy.GetBoundingRectangle()))
            //        {
            //            this.Kill();
            //            break;
            //        }
            //    }
            //}


            return base.Update(gameTime);
        }

        #endregion

        #region Public Methods

        public void StartJumping()
        {
            AudioManager.Jump.Play();
            this.jumpTime = new TimeSpan();
            this.velocity.Y = -2f;
        }

        private void BuildUpJump(TimeSpan elapsedTime)
        {
            this.velocity.Y = -1.4f;
            this.jumpTime += elapsedTime;
            if (jumpTime >= maxJumpTime)
                FinalizeJump();
        }

        public void FinalizeJump()
        {
            this.velocity.Y = -.85f;
            this.jumpTime = null;
        }

        #endregion

    }
}
